/*
* Terrier - Terabyte Retriever
* Webpage: http://terrier.org
* Contact: terrier{a.}dcs.gla.ac.uk
* University of Glasgow - School of Computing Science
* http://www.gla.ac.uk/
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is ApplicationSetup.java.
*
* The Original Code is Copyright (C) 2004-2011 the University of Glasgow.
* All Rights Reserved.
*
* Contributor(s):
* Gianni Amati <gba{a.}fub.it> (original author)
* Vassilis Plachouras <vassilis{a.}dcs.gla.ac.uk>
* Ben He <ben{a.}dcs.gla.ac.uk>
* Craig Macdonald <craigm{a.}dcs.gla.ac.uk>
*/
package org.terrier.utility;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
/**
* <p>This class retrieves and provides access
* to all the constants and parameters for
* the system. When it is statically initialised,
* it loads the properties file specified by the system property
* <tt>terrier.setup</tt>. If this is not specified, then the default value is
* the value of the <tt>terrier.home</tt> system property, appended by <tt>etc/terrier.properties</tt>.
* <BR/>
* eg <tt>java -Dterrier.home=$TERRIER_HOME -Dterrier.setup=$TERRIER_HOME/etc/terrier.properties TrecTerrier </tt>
* </p><p>
* <b>System Properties used:</b>
* <table><tr><td>
* <tt>terrier.setup</tt></td><td>Specifies where the terrier.properties file can be found.
* </td></tr>
* <tr><td><tt>terrier.home</tt></td><td>Specified where Terrier has been installed, if the terrier.properties
* file cannot be found, or the terrier.properties file does not specify the <tt>terrier.home</tt> in it.
* <br><b>NB:</b>In the future, this may further default to $TERRIER_HOME from the environment.
* </td><tr><td><tt>file.separator</tt></td><td>What separates directory names in this platform. Set automatically by Java</td></tr>
* <tr><td><tt>line.separator</tt></td><td>What separates lines in a file on this platform. Set automatically by Java</td>
* </table>
* </p><p>
* In essence, for Terrier to function properly, you need to specify one of the following on the command line:
* <ul><li><tt>terrier.setup</tt> pointing to a terrier.properties file containing a <tt>terrier.home</tt> value.
* </li>OR<li><tt>terrier.home</tt>, and Terrier will use a properties file at etc/terrier.properties, if it finds one.</li></ul>
* </p>
* <p>Any property defined in the properties file can be overridden as follows:</p>
* <ul>
* <li>If the system property <tt>terrier.usecontext</tt> is equal to <tt>true</tt>, then a Context
* object is used to override the properties defined in the file.</li>
* <li>If the system property <tt>terrier.usecontext</tt> is equal to <tt>false</tt>, then
* system properties are used to override the properties defined in the file.</li>
* </ul>
* @author Gianni Amati, Vassilis Plachouras, Ben He, Craig Macdonald
*/
public class ApplicationSetup {
/** Interface for plugins. Plugins are loaded at initialisation time,
* specified by the property <tt>terrier.plugins</tt>
* @since 2.2
*/
public interface TerrierApplicationPlugin
{
/** Called by ApplicationSetup to initialise the plugin */
void initialise() throws Exception;
}
/** Current Terrier version */
public static final String TERRIER_VERSION = "3.5";
static Logger logger = null;
/** Default log4j config Terrier loads if no TERRIER_ETC/terrier-log.xml file exists
* @since 1.1.0
*/
public static final String DEFAULT_LOG4J_CONFIG =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
+ "<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">"
+ "<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\">"
+ " <appender name=\"console\" class=\"org.apache.log4j.ConsoleAppender\">"
+ " <param name=\"Target\" value=\"System.err\"/>"
+ " <layout class=\"org.apache.log4j.SimpleLayout\"/>"
+ " </appender>"
+ " <root>"
+ " <priority value=\"info\" />"
+ " <appender-ref ref=\"console\" />"
+ " </root>"
+ "</log4j:configuration>";
/**
* The properties object in which the
* properties from the file are read.
*/
protected static final Properties appProperties = new Properties();
protected static final Properties UsedAppProperties = new Properties();;
//Operating system dependent constants
/**
* The file separator used by the operating system. Defaults to
* the system property <tt>file.separator</tt>.
*/
public static String FILE_SEPARATOR = System.getProperty("file.separator");
/**
* The new line character used by the operating system. Defaults to
* the system property <tt>line.separator</tt>.
*/
public static String EOL = System.getProperty("line.separator");
//Application specific constants. Should be specified in the properties file.
/**
* The directory under which the application is installed.
* It corresponds to the property <tt>terrier.home</tt> and it
* should be set in the properties file, or as a property on the
* command line.
*/
public static String TERRIER_HOME;
/**
* The directory under which the configuration files
* of Terrier are stored. The corresponding property is
* <tt>terrier.etc</tt> and it should be set
* in the properties file. If a relative path is given,
* TERRIER_HOME will be prefixed.
*/
public static String TERRIER_ETC;
/**
* The name of the directory where installation independent
* read-only data is stored. Files like stopword lists, and
* example and testing data are examples. The corresponding
* property is <tt>terrier.share</tt> and its default value is
* <tt>share</tt>. If a relative path is given, then TERRIER_HOME
* will be prefixed. */
public static String TERRIER_SHARE;
/**
* The name of the directory where the data structures
* and the output of Terrier are stored. The corresponding
* property is <tt>terrier.var</tt> and its default value is
* <tt>var</tt>. If a relative path is given,
* TERRIER_HOME will be prefixed.
*/
public static String TERRIER_VAR;
/**
* The name of the directory where the inverted
* file and other data structures are stored.
* The default value is InvFileCollection but it
* can be overridden with the property <tt>terrier.index.path</tt>.
* If a relative path is given, TERRIER_VAR will be prefixed.
*/
public static String TERRIER_INDEX_PATH;
/**
* The name of the file that contains the
* list of resources to be processed during indexing.
* The contents of this file are collection implementation
* dependent. For example, for a TREC collection, this file
* must contain the list of files to index.
* The corresponding property is <tt>collection.spec</tt>
* and by default its value is <tt>collection.spec</tt>.
* If a relative path is given, TERRIER_ETC will be prefixed.
*/
public static String COLLECTION_SPEC;
//TREC SPECIFIC setup
/**
* The name of the directory where the results
* are stored. The corresponding property is
* <tt>trec.results</tt> and the default value is
* <tt>results</tt>. If a relative path is given,
* TERRIER_VAR will be prefixed.
*/
public static String TREC_RESULTS;
/**
* @deprecated As of Terrier 3.5
* The name of the file that contains a list of
* files where queries are stored. The corresponding property
* is <tt>trec.topics.list</tt> and the default value
* is <tt>trec.topics.list</tt>. If a relative path is given,
* TERRIER_ETC will be prefixed.
*/
public static String TREC_TOPICS_LIST;
/**
* @deprecated As of Terrier 3.5
* The name of the file that contains a list of qrels files
* to be used for evaluation. The corresponding property is
* <tt>trec.qrels</tt> and its default value is <tt>trec.qrels</tt>.
* If a relative path is given, TERRIER_ETC will be prefixed.
*/
public static String TREC_QRELS;
/**
* The suffix of the files, where the results are stored.
* It corresponds to the property <tt>trec.results.suffix</tt>
* and the default value is <tt>.res</tt>.
*/
public static String TREC_RESULTS_SUFFIX;
/**
* @deprecated As of Terrier 3.5
* The filename of the file that contains
* the weighting models to be used. The corresponding
* property is <tt>trec.models</tt> and the default value
* is <tt>trec.models</tt>. If a relative path is given, then
* it is prefixed with TERRIER_ETC.
*/
public static String TREC_MODELS;
//end of TREC specific section
/**
* The suffix of the inverted file. The corresponding
* property is <tt>if.suffix</tt> and by default
* the value of this property is <tt>.if</tt>
*/
//public static String IFSUFFIX;
/**
* The suffix of the file that contains the
* lexicon. The corresponding property is
* <tt>lexicon.suffix</tt> and by default
* the value of this property is <tt>.lex</tt>
*/
//public static String LEXICONSUFFIX;
/**
* The suffix of the file that contains the
* document index. The corresponding property
* is <tt>doc.index.suffix</tt> and by default
* the value of this property is <tt>.docid</tt>
*/
//public static String DOC_INDEX_SUFFIX;
/**
* The suffix of the lexicon index file
* that contains the offset of each term
* in the lexicon. The corresponding
* property is <tt>lexicon.index.suffix</tt> and
* by default its value is .lexid.
*/
//public static String LEXICON_INDEX_SUFFIX;
/** The suffix of the lexicon hash file. Corresponding property
* is <tt>lexicon.hash.suffix</tt>, default is ".lexhash". */
//public static String LEXICON_HASH_SUFFIX;
/**
* The suffix of the file that contains
* the collection statistics. It corresponds
* to the property <tt>log.suffix</tt> and
* by default the value of this property is <tt>.log</tt>
*/
//public static String LOG_SUFFIX;
/**
* The suffix of the file that contains
* the index properties. It corresponds
* to the property <tt>indexproperties.suffix</tt> and
* by default the value of this property is <tt>.log</tt>
*/
//public static String PROPERTIES_SUFFIX;
/**
* The suffix of the direct index. It corresponds
* to the property <tt>df.suffix</tt> and by default
* the value of this property is <tt>.df</tt>
*/
//public static String DF_SUFFIX;
/**
* The prefix of the temporary merged files,
* which are created during merging the
* lexicon files. It corresponds to the property
* <tt>merge.prefix</tt> and the default value is <tt>MRG_</tt>.
*/
//public static String MERGE_PREFIX;
/**
* A progressive number which is assigned to the
* temporary lexicon files built during the indexing.
* It is used to keep track of the order with which
* the temporary files were created. It corresponds to
* the property <tt>merge.temp.number</tt> and the default value
* is <tt>100000</tt>
*/
//public static int MERGE_TEMP_NUMBER;
/**
* The number of documents to be processed as a group during indexing.
* For each such group of documents, a temporary lexicon is built,
* and after indexing, all temporary lexicons are merged in order to
* create a single lexicon. It corresponds to the property
* <tt>bundle.size</tt> and the default value is <tt>2000</tt>.
*/
//public static int BUNDLE_SIZE;
/**
* The number of bytes used to store a term. Corresponds to MAX_TERM_LENGTH
* if not using UTF, and 3*MAX_TERM_LENGTH if using UTF. No property is associated.
* UTF support can be enabled by setting the property <tt>string.use_utf</tt> to
* true.
*/
//public static int STRING_BYTE_LENGTH;
/** The number of bytes used to store a document number. It corresponds
* to the property <tt>docno.byte.length</tt>, and the default value
* is 20.
* @since 1.1.0 */
//public static int DOCNO_BYTE_LENGTH;
/** The maximum size of a term. It corresponds to the the property
* <tt>max.term.length</tt>, and the default value is 20.
* @since 1.1.0 */
public static int MAX_TERM_LENGTH;
/**
* Ignore or not empty documents. That is, if it is true, then a document
* that does not contain any terms will have a corresponding entry in the
* .docid file and the total number of documents in the statistics will be
* the total number of documents in the collection, even if some of them
* are empty. It corresponds to the property <tt>ignore.empty.documents</tt>
* and the default value is false.
*/
public static boolean IGNORE_EMPTY_DOCUMENTS;
/**
* The prefix of the data structures' filenames.
* It corresponds to the property <tt>terrier.index.prefix</tt>
* and the default value is <tt>data</tt>.
*/
public static String TERRIER_INDEX_PREFIX;
/** The filename of the inverted file.*/
//public static String INVERTED_FILENAME;
/** The filename of the direct file.*/
//public static String DIRECT_FILENAME;
/** The filename of the document index.*/
//public static String DOCUMENT_INDEX_FILENAME;
/** The filename of the lexicon file.*/
//public static String LEXICON_FILENAME;
/** The filename of the lexicon index file.*/
//public static String LEXICON_INDEX_FILENAME;
/** The filename of the log (statistics) file.*/
//public static String LOG_FILENAME;
//query expansion properties
/**
* The number of terms added to the original query.
* The corresponding property is <tt>expansion.terms</tt>
* and the default value is <tt>10</tt>.
*/
public static int EXPANSION_TERMS;
/**
* The number of top ranked documents considered for
* expanding the query. The corresponding property is
* <tt>expansion.documents</tt> and the default value is <tt>3</tt>.
*/
public static int EXPANSION_DOCUMENTS;
/**
* @deprecated As of Terrier 3.5
* The name of the file which contains the query expansion
* methods used. The corresponding property is
* <tt>expansion.models</tt> and the default
* value is <tt>qemodels</tt>. If a relative path is given,
* it is prefixed with TERRIER_ETC.
*/
public static String EXPANSION_MODELS;
//block related properties
/**
* The size of a block of terms in a document.
* The corresponding property is <tt>blocks.size</tt>
* and the default value is 1.
*/
public static int BLOCK_SIZE;
/**
* The maximum number of blocks in a document.
* The corresponding property is <tt>blocks.max</tt>
* and the default value is 100000.
*/
public static int MAX_BLOCKS;
/**
* Specifies whether block information will
* be used for indexing. The corresponding property is
* <tt>block.indexing</tt> and the default value is false.
* The value of this property cannot be modified after
* the index of a collection has been built.
*/
public static boolean BLOCK_INDEXING = false;
/**
* Specifies whether fields will be used for querying.
* The corresponding property is <tt>field.querying</tt> and
* the default value is false.
*/
public static boolean FIELD_QUERYING = false;
//new
/**
* Memory threshold in the single pass inversion method. If a memory check is below this value, the postings
* in memory are written to disk. Default is 50 000 000 (50MB) and 100 000 000 (100MB) for 32bit and 64bit
* JVMs respectively, and can be configured using the property
* <tt>memory.reserved</tt>.
*/
public static int MEMORY_THRESHOLD_SINGLEPASS;
/**
* Number of documents between each memory check in the single pass inversion method. The default value is 20,
* and this can be configured using the property <tt>docs.check</tt>.
*/
public static int DOCS_CHECK_SINGLEPASS;
/** Checks whether a context is used instead of the properties file */
private static boolean useContext = false;
/** The configuration file used by log4j */
public static String LOG4J_CONFIG = null;
/**
* The context that replaces the properties file if the
* property <tt>terrier.usecontext</tt> is equal to <tt>true</tt>.
*/
private static Context envCtx = null;
static {
bootstrapInitialisation();
}
/** forces ApplicatinSetup initilisation */
public static void bootstrapInitialisation()
{
useContext = Boolean.parseBoolean(System.getProperty("terrier.usecontext", "false"));
String propertiesFile = null;
String terrier_home = null;
String terrier_etc = null;
try {
if (useContext)
{
//
Context initCtx = null;
try{
initCtx = (Context)( new InitialContext());
envCtx = (Context) initCtx.lookup("java:comp/env");
}catch(NamingException ne) {
throw new RuntimeException("NamingException loading an InitialContext or EnvironmentContext",ne);
}
try{
terrier_home = (String)envCtx.lookup("terrier.home");
}catch(NamingException ne) {
throw new RuntimeException("NamingException finding terrier variables from envCtx",ne);
}
try{
terrier_etc = (String)envCtx.lookup("terrier.etc");
} catch(NamingException ne) {
throw new RuntimeException("NamingException finding terrier variables from envCtx",ne);
}
try{
propertiesFile = (String)envCtx.lookup("terrier.setup");
}catch(NamingException ne) {
throw new RuntimeException("NamingException finding terrier variables from envCtx",ne);
}
if (propertiesFile == null)
if (terrier_etc == null)
terrier_etc = terrier_home +FILE_SEPARATOR+"etc";
propertiesFile = terrier_etc+FILE_SEPARATOR+"terrier.properties";
}
else
{
terrier_home = System.getProperty("terrier.home", "");
terrier_etc = System.getProperty("terrier.etc", terrier_home +FILE_SEPARATOR+"etc");
propertiesFile = System.getProperty("terrier.setup", terrier_etc + FILE_SEPARATOR+"terrier.properties");
}
//if system property terrier.setup is not specified, then it is
//assumed that the properties file is at ./etc/terrier.properties
//System.err.println("Properties file is "+propertiesFile);
TERRIER_HOME = getProperty("terrier.home", terrier_home);
FileInputStream in = new FileInputStream(propertiesFile);
configure(new BufferedInputStream(in));
in.close();
} catch (java.io.FileNotFoundException fnfe) {
System.out.println("WARNING: The file terrier.properties was not found at location "+propertiesFile);
System.out.println(" Assuming the value of terrier.home from the corresponding system property.");
} catch (java.io.IOException ioe) {
System.err.println(
"Input/Output Exception during initialization of ");
System.err.println("org.terrier.utility.ApplicationSetup: "+ioe);
System.err.println("Stack trace follows.");
ioe.printStackTrace();
}
/*
* The property terrier.home does not have a default value, so it has
* to be specified by the user in the terrier.properties file. If there
* is no terrier.properties specified, then we try to read a value from
* the system property terrier.home. Ideally, the value of terrier.home
* would be $ENV{TERRIER_HOME} but java geniuses, in their infinite wisdom
* have deprecated System.getEnv() in Java 1.4.
*/
TERRIER_HOME = getProperty("terrier.home", terrier_home);
if (TERRIER_HOME.equals("")) {
System.err.println("Please ensure that the property terrier.home");
System.err.println("is specified in the file terrier.properties,");
System.err.println("or as a system property in the command line.");
}
loadCommonProperties();
}
/** Loads the ApplicationSetup variables, e.g. ApplicationSetup.TERRIER_HOME */
public static void loadCommonProperties()
{
TERRIER_ETC = makeAbsolute( getProperty("terrier.etc","etc"), TERRIER_HOME);
TERRIER_VAR = makeAbsolute( getProperty("terrier.var","var"), TERRIER_HOME);
TERRIER_SHARE = makeAbsolute( getProperty("terrier.share", "share"), TERRIER_HOME);
TERRIER_INDEX_PATH = makeAbsolute(getProperty("terrier.index.path", "index"), TERRIER_VAR);
TERRIER_INDEX_PREFIX = getProperty("terrier.index.prefix", "data");
//TREC specific
TREC_TOPICS_LIST = makeAbsolute( getProperty("trec.topics.list","trec.topics.list"), TERRIER_ETC);
TREC_QRELS = makeAbsolute( getProperty("trec.qrels","trec.qrels"), TERRIER_ETC);
TREC_RESULTS = makeAbsolute(getProperty("trec.results", "results"), TERRIER_VAR);
TREC_MODELS = makeAbsolute(getProperty("trec.models", "trec.models"), TERRIER_ETC);
TREC_RESULTS_SUFFIX = getProperty("trec.results.suffix", ".res");
//The following properties specify the filenames and suffixes
COLLECTION_SPEC = makeAbsolute(getProperty("collection.spec", "collection.spec"), TERRIER_ETC);
//IFSUFFIX = getProperty("if.suffix", ".if");
//LEXICONSUFFIX = getProperty("lexicon.suffix", ".lex");
//LEXICON_INDEX_SUFFIX = getProperty("lexicon.index.suffix", ".lexid");
//LEXICON_HASH_SUFFIX = getProperty("lexicon.hash.suffix",".lexhash");
//DOC_INDEX_SUFFIX = getProperty("doc.index.suffix", ".docid");
//LOG_SUFFIX = getProperty("log.suffix", ".log");
//DF_SUFFIX = getProperty("df.suffix", ".df");
//PROPERTIES_SUFFIX = getProperty("indexproperties.suffix", ".properties");
//the following two properties are related to the indexing of
//documents. The prefix mergepref and and the number prog.nr
//specify the names of the temporary lexicon created
//during creating a global lexicon.
//MERGE_PREFIX = getProperty("merge.prefix", "MRG_");
//MERGE_TEMP_NUMBER = Integer.parseInt(getProperty("merge.temp.number", "100000"));
//if a document is empty, that is it does not contain any terms,
//we have the option to add it to the index, or not. By default,
//empty documents are added to the index.
IGNORE_EMPTY_DOCUMENTS = Boolean.parseBoolean(getProperty("ignore.empty.documents", "false"));
//During the indexing process, we process and create temporary structures
//for bundle.size files.
//BUNDLE_SIZE = Integer.parseInt(getProperty("bundle.size", "2000"));
//the maximum size of a term (string)
MAX_TERM_LENGTH = Integer.parseInt(getProperty("max.term.length", "20"));
//the maximum number of bytes used to store a term.
//if (Boolean.parseBoolean(ApplicationSetup.getProperty("string.use_utf", "false")))
// STRING_BYTE_LENGTH = MAX_TERM_LENGTH *3;
//else
// STRING_BYTE_LENGTH = MAX_TERM_LENGTH;
//the maximum number of bytes used to store a document number.
//DOCNO_BYTE_LENGTH = Integer.parseInt(getProperty("docno.byte.length", "20"));
//query expansion properties
EXPANSION_TERMS = Integer.parseInt(getProperty("expansion.terms", "10"));
EXPANSION_DOCUMENTS = Integer.parseInt(getProperty("expansion.documents", "3"));
EXPANSION_MODELS = makeAbsolute(getProperty("expansion.models", "qemodels"), TERRIER_ETC);
//html tags and proximity related properties
BLOCK_INDEXING = Boolean.parseBoolean(getProperty("block.indexing", "false"));
BLOCK_SIZE = Integer.parseInt(getProperty("blocks.size", "1"));
MAX_BLOCKS = Integer.parseInt(getProperty("blocks.max", "100000"));
FIELD_QUERYING = Boolean.parseBoolean(getProperty("field.querying", "false"));
//double the amount of memory if using 64bit JVM.
MEMORY_THRESHOLD_SINGLEPASS = Integer.parseInt(getProperty("memory.reserved",
System.getProperty("sun.arch.data.model", "32").equals("64") ? "100000000" : "50000000"));
DOCS_CHECK_SINGLEPASS = Integer.parseInt(getProperty("docs.check", "20"));
LOG4J_CONFIG = makeAbsolute(getProperty("log4j.config", "terrier-log.xml"), TERRIER_ETC);
//check for an existing log4j configuration before configuring
if (! isLog4JConfigured())
{
//setup log4j
if (new File(LOG4J_CONFIG).exists())
{
DOMConfigurator.configure(LOG4J_CONFIG);
}
else
{
//slightly ugly hack: record a good default configuration as a String in this class, and load that
//emulating DOMConfigurator.configure(Reader)
//see http://svn.apache.org/viewvc/logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/xml/DOMConfigurator.java?revision=311462&view=markup
new DOMConfigurator().doConfigure(new StringReader(DEFAULT_LOG4J_CONFIG), org.apache.log4j.LogManager.getLoggerRepository());
}
}
//setup the logger for this class
logger = Logger.getLogger(ApplicationSetup.class);
//setup default filename
setupFilenames();
//setup any plugins
setupPlugins();
}
//@SuppressWarnings("unchecked")
private static boolean isLog4JConfigured()
{
// boolean log4jConfigured = false;
// java.util.Enumeration en = Logger.getRootLogger().getAllAppenders();
// if (!(en instanceof org.apache.log4j.helpers.NullEnumeration))
// {
// log4jConfigured = true;
// }
// else
// {
// java.util.Enumeration cats = org.apache.log4j.LogManager.getCurrentLoggers();
// while (cats.hasMoreElements())
// {
// Logger c = (org.apache.log4j.Logger) cats.nextElement();
// if (!(c.getAllAppenders() instanceof org.apache.log4j.helpers.NullEnumeration))
// {
// log4jConfigured = true;
// }
// }
// }
//return log4jConfigured;
return false;
}
/** Loads the common Terrier properties from the specified InputStream */
public static void configure(InputStream propertiesStream) throws IOException
{
appProperties.load(propertiesStream);
loadCommonProperties();
}
/**
* Returns the value for the specified property, given
* a default value, in case the property was not defined
* during the initialization of the system.
*
* The property values are read from the properties file. If the value
* of the property <tt>terrier.usecontext</tt> is true, then the properties
* file is overridden by the context. If the value of the property
* <tt>terrier.usecontext</tt> is false, then the properties file is overridden
* @param propertyKey The property to be returned
* @param defaultValue The default value used, in case it is not defined
* @return the value for the given property.
*/
public static String getProperty(String propertyKey, String defaultValue) {
String propertyValue = appProperties.getProperty(propertyKey, defaultValue);
if (useContext) {//context is used
try{
propertyValue = (String)envCtx.lookup(propertyKey);
if (propertyValue != null)
UsedAppProperties.setProperty(propertyKey, propertyValue);
}catch(NamingException ne) {
//in case of an exception, ie the property is not defined
//in the context, use the value from the properties file,
//or the default value.
}
} else {
propertyValue = System.getProperty(propertyKey, propertyValue);
if (propertyValue != null)
UsedAppProperties.setProperty(propertyKey, propertyValue);
//in case there is no system property, the returned property value
//is the one read from the properties file, or the default value.
}
return propertyValue;
}
/** Returns a properties object detailing all the properties fetched during the lifetime of this class.
* It is of note that this is NOT the underlying appProperties table, as to update that would mean that
* properties fetched using their defaults, could not have different defaults in different places. */
public static Properties getUsedProperties()
{
return UsedAppProperties;
}
/** Returns the underlying properties object for ApplicationSetup */
public static Properties getProperties()
{
return appProperties;
}
/**
* Sets a value for the specified property. The properties
* set with this method are not saved in the properties file.
* @param propertyKey the name of the property to set.
* @param value the value of the property to set.
*/
public static void setProperty(String propertyKey, String value) {
appProperties.setProperty(propertyKey, value);
}
/** set a property value only if it has not already been set
* @param propertyKey the name of the property to set.
* @param defaultValue the value of the property to set.
*/
public static void setDefaultProperty(String propertyKey, String defaultValue) {
if (getProperty(propertyKey,null) != null)
setProperty(propertyKey, defaultValue);
}
/**
* Sets up the names of the inverted file, the direct file,
* the document index file and the lexicon file.
* @deprecated
*/
public static void setupFilenames() {}
/** list of loaded plugins */
protected static List<TerrierApplicationPlugin> loadedPlugins = null;
/** Calls the initialise method of any plugins named in terrier.plugins */
protected static void setupPlugins()
{
loadedPlugins = new LinkedList<TerrierApplicationPlugin>();
final String[] pluginNames = getProperty("terrier.plugins", "").split("\\s*,\\s*");
for (String pluginName : pluginNames)
{
if (pluginName.length() == 0)
continue;
if (pluginName.startsWith("uk.ac.gla.terrier.utility"))
pluginName = pluginName.replaceFirst("uk.ac.gla.terrier.utility", "org.terrier.utility");
try{
TerrierApplicationPlugin plugin = Class.forName(pluginName).asSubclass(TerrierApplicationPlugin.class).newInstance();
plugin.initialise();
loadedPlugins.add(plugin);
} catch (Exception e) {
//logger.warn("Problem loading plugin named "+ pluginName, e);
}
}
}
/** Return a loaded plugin by name. Returns null if a plugin
* of that name has not been loaded */
public TerrierApplicationPlugin getPlugin(String name)
{
for (TerrierApplicationPlugin p : loadedPlugins)
if (p.getClass().getName().equals(name))
return p;
return null;
}
/**
* Checks whether the given filename is absolute and if not, it
* adds on the default path to make it absolute.
* If a URI scheme is present, the filename is assumed to be absolute
* @param filename String the filename to make absolute
* @param DefaultPath String the prefix to add
* @return the absolute filename
*/
public static String makeAbsolute(String filename, String DefaultPath)
{
if(filename == null)
return null;
if(filename.length() == 0)
return filename;
if (filename.matches("^\\w+:.*"))
return filename;
if ( new File(filename).isAbsolute() )
return filename;
if (! DefaultPath.endsWith(FILE_SEPARATOR))
{
DefaultPath = DefaultPath + FILE_SEPARATOR;
}
return DefaultPath+filename;
}
/** Clears ApplicationSetup of all properties */
public static void clearAllProperties()
{
appProperties.clear();
UsedAppProperties.clear();
}
}